package com.verykim.video;

//import java.net.URLDecoder;
//import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.TimeZone;

import com.google.appengine.api.blobstore.BlobKey;
import com.google.appengine.api.blobstore.BlobstoreService;
import com.google.appengine.api.blobstore.BlobstoreServiceFactory;
import com.google.appengine.api.datastore.AsyncDatastoreService;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.Filter;
import com.google.appengine.api.datastore.Text;
import com.google.appengine.api.datastore.Query.CompositeFilterOperator;
import com.google.appengine.api.datastore.Query.FilterPredicate;
import com.google.appengine.api.datastore.Query.SortDirection;

public final class Video {

	final static String P_TITLE = "title";// 片名
	final static String P_PERIOD = "period";// 年代
	final static String P_AREA = "area";// 地区
	final static String P_DIRECTOR = "director";// 导演
	final static String P_ACTORS = "actors";// 主演
	final static String P_VIEWS = "views";// 浏览数
	final static String P_RANK = "rank";// 随机种子
	final static String P_DATE = "date";// 创建时间

	final static String UP_SUMMARY = "summary";// 摘要
	final static String UP_CONTENT = "content";// 内容
	final static String UP_QVOD = "qvod";//
	final static String UP_BDHD = "bdhd";//
	final static String UP_ED2K = "ed2k";//
	final static String UP_MAGNET = "magnet";// 磁力链接
	final static String UP_THUNDER = "thunder";//
	final static String UP_BLOBKEY = "blobkey";// 略缩图

	private Key CategoryKey;

	private String title;
	private int period;
	private String area;
	private String director;
	private List<String> actors;

	private String summary;
	private String content;

	private List<String> qvod;
	private List<String> bdhd;
	private List<String> ed2k;

	private List<String> thunder;
	private List<String> magnet;

	private BlobKey blobkey;

	public void Title(final String title) {
		this.title = title;
	}

	public void Period(final int period) {
		this.period = period;
	}

	public void Area(final String area) {
		this.area = area;
	}

	public void Director(final String director) {
		this.director = director;
	}

	public void Summary(final String summary) {
		this.summary = summary;
	}

	public void Content(final String content) {
		this.content = content;
	}

	public void Actors(final String[] actors) {
		if (null != actors) {
			this.actors = Arrays.asList(actors);
		}
	}

	public void Qvod(final String[] qvod) {
		if (null != qvod) {
			this.qvod = Arrays.asList(qvod);
		}
	}

	public void Bdhd(final String[] bdhd) {
		if (null != bdhd) {
			this.bdhd = Arrays.asList(bdhd);
		}
	}

	public void Ed2k(final String[] ed2k) {
		if (null != ed2k) {
			this.ed2k = Arrays.asList(ed2k);
		}
	}

	public void Thunder(final String[] thunder) {
		if (null != thunder) {
			this.thunder = Arrays.asList(thunder);
		}
	}

	public void Magnet(final String[] magnet) {
		if (null != magnet) {
			this.magnet = Arrays.asList(magnet);
		}
	}

	public void Blobkey(final BlobKey blobkey) {
		this.blobkey = blobkey;
	}

	Video(final String category) {
		this.CategoryKey = KeyFactory.createKey(Category.class.getSimpleName(),
				category);
	}

	public static boolean add(final Video video) throws Exception {

		final DatastoreService ds = DatastoreServiceFactory
				.getDatastoreService();
		try {

			final Entity E = new Entity(Video.class.getSimpleName(),
					video.title, video.CategoryKey);

			E.setProperty(P_PERIOD, video.period);
			E.setProperty(P_AREA, video.area);
			E.setProperty(P_DIRECTOR, video.director);
			E.setProperty(P_ACTORS, video.actors);
			E.setProperty(P_VIEWS, 1);

			final Calendar cal = Calendar.getInstance();
			cal.setTimeZone(TimeZone.getTimeZone("GMT+8"));
			E.setProperty(P_DATE, cal.getTime());

			final double rank = Math.random();
			E.setProperty(P_RANK, (long) (rank * 100000));

			E.setUnindexedProperty(UP_SUMMARY, video.summary);
			E.setUnindexedProperty(UP_CONTENT, new Text(video.content));
			E.setUnindexedProperty(UP_QVOD, video.qvod);
			E.setUnindexedProperty(UP_BDHD, video.bdhd);
			E.setUnindexedProperty(UP_ED2K, video.ed2k);
			E.setUnindexedProperty(UP_MAGNET, video.magnet);
			E.setUnindexedProperty(UP_THUNDER, video.thunder);
			E.setUnindexedProperty(UP_BLOBKEY, video.blobkey);
			ds.put(E);
		} catch (Exception e) {
			return false;
		} finally {
		}
		return true;
	}

	public static Entity video(final String category, final String title) {

		final Key ck = KeyFactory.createKey(Category.class.getSimpleName(),
				category);
		final Key vk = KeyFactory.createKey(ck, Video.class.getSimpleName(),
				title);
		return video(vk);
	}

	public static Entity video(final Key vk) {
		if (null != vk) {
			final DatastoreService ds = DatastoreServiceFactory
					.getDatastoreService();
			try {
				return ds.get(vk);
			} catch (EntityNotFoundException e) {
				e.printStackTrace();
				return null;
			}
		} else {
			return null;
		}
	}

	public static Iterator<Entity> KeysOnlyVideos(final boolean isAll) {
		final DatastoreService ds = DatastoreServiceFactory
				.getDatastoreService();
		final Query q = new Query(Video.class.getSimpleName()).setKeysOnly();
		if (!isAll) {
			q.setFilter(new FilterPredicate(Video.P_DATE,
					Query.FilterOperator.GREATER_THAN, new Date(System
							.currentTimeMillis() - 60 * 60 * 24 * 1000)));
		}
		q.addSort(Video.P_DATE, SortDirection.DESCENDING);
		final PreparedQuery pq = ds.prepare(q);
		return pq.asIterator();
	}

	public static List<Entity> videos() {
		final Query q = new Query(Video.class.getSimpleName());
		final DatastoreService ds = DatastoreServiceFactory
				.getDatastoreService();
		final PreparedQuery pq = ds.prepare(q);
		return pq.asList(FetchOptions.Builder.withDefaults());
	}

	public static List<Entity> videos(final String category,
			final String period, final String area, final boolean random,
			final String date, final int PageSize) {
		//boolean reverse = false;
		final Query q = new Query(Video.class.getSimpleName());
		if (null != category) {
			q.setAncestor(KeyFactory.createKey(Category.class.getSimpleName(),
					category));
		}

		final Collection<Filter> fil = new ArrayList<Filter>();

		if (null != period) {
			fil.add(new FilterPredicate(Video.P_PERIOD,
					Query.FilterOperator.EQUAL, Integer.parseInt(period)));
		}
		if (null != area) {
			fil.add(new FilterPredicate(Video.P_AREA,
					Query.FilterOperator.EQUAL, area));
		}

		if (random) {// 只允许对一个属性使用不等式过滤器
			final long d1 = (long) (100000 * Math.random());
			final long d2 = (long) (100000 * Math.random());
			fil.add(new FilterPredicate(Video.P_RANK,
					Query.FilterOperator.GREATER_THAN, Math.min(d1, d2)));
			fil.add(new FilterPredicate(Video.P_RANK,
					Query.FilterOperator.LESS_THAN, Math.max(d1, d2)));
			// q.setFilter(CompositeFilterOperator.and(
			// new FilterPredicate(Video.P_RANK,
			// Query.FilterOperator.GREATER_THAN, Math.min(d1, d2)),
			// new FilterPredicate(Video.P_RANK,
			// Query.FilterOperator.LESS_THAN, Math.max(d1, d2))));
			q.addSort(Video.P_RANK, d1 > d2 ? SortDirection.DESCENDING
					: SortDirection.ASCENDING);
		} else {
			if (null != date) {
				if (date.toLowerCase().equals("today")) {
					final Calendar cal = Calendar.getInstance();
					cal.setTimeZone(TimeZone.getTimeZone("GMT+8"));
					cal.set(Calendar.HOUR_OF_DAY, 0);
					cal.set(Calendar.MINUTE, 0);
					cal.set(Calendar.SECOND, 0);
					final long b = cal.getTimeInMillis();
					fil.add(new FilterPredicate(Video.P_DATE,
							Query.FilterOperator.GREATER_THAN, new Date(b)));
					cal.set(Calendar.HOUR_OF_DAY, 23);
					cal.set(Calendar.MINUTE, 59);
					cal.set(Calendar.SECOND, 59);
					final long e = cal.getTimeInMillis();
					fil.add(new FilterPredicate(Video.P_DATE,
							Query.FilterOperator.LESS_THAN_OR_EQUAL,
							new Date(e)));
				} else {
					final long d = Long.parseLong(date);
					if (d > 0) {
						fil.add(new FilterPredicate(Video.P_DATE,
								Query.FilterOperator.LESS_THAN, new Date(d)));
					} else if (d < 0) {
						fil.add(new FilterPredicate(Video.P_DATE,
								Query.FilterOperator.GREATER_THAN, new Date(-d)));
						//reverse = true;
					}
				}
			}
		}

		if (!fil.isEmpty()) {
			int size = fil.size();
			if (size == 1) {
				q.setFilter(fil.iterator().next());
			} else {
				q.setFilter(new Query.CompositeFilter(
						CompositeFilterOperator.AND, fil));
			}
		}
		
		q.addSort(Video.P_DATE, SortDirection.DESCENDING);
		
		/*
		 * q.addSort(Video.P_DATE, reverse ? SortDirection.DESCENDING :
		 * SortDirection.ASCENDING);
		 */

		final FetchOptions fo = FetchOptions.Builder.withLimit(PageSize);
		final DatastoreService ds = DatastoreServiceFactory
				.getDatastoreService();
		final List<Entity> list = ds.prepare(q).asList(fo);
		/*
		if (reverse) {
			Collections.reverse(list);
		}
		*/
		return list;
	}

	public static boolean delete(final String category, final String title) {
		try {
			final Key ck = KeyFactory.createKey(Category.class.getSimpleName(),
					category);
			final Key vk = KeyFactory.createKey(ck,
					Video.class.getSimpleName(), title);
			final Entity E = Video.video(category, title);
			final Object BLOBKEY = E.getProperty(Video.UP_BLOBKEY);
			if (null != BLOBKEY) {
				delete(vk, (BlobKey) BLOBKEY);
			}
		} catch (Exception e) {
			return false;
		}
		return true;
	}

	public static boolean delete(final String KeyString) {
		final AsyncDatastoreService ads = DatastoreServiceFactory
				.getAsyncDatastoreService();
		try {
			final Key k = KeyFactory.stringToKey(KeyString);
			ads.delete(k);
		} catch (Exception e) {
			return false;
		}
		return true;
	}

	public static boolean delete(final Key vk, final BlobKey blobKey) {
		final AsyncDatastoreService ads = DatastoreServiceFactory
				.getAsyncDatastoreService();
		final BlobstoreService bs = BlobstoreServiceFactory
				.getBlobstoreService();
		try {
			ads.delete(vk);
			if (null != blobKey) {
				bs.delete(blobKey);
			}
		} catch (Exception e) {
			return false;
		}
		return true;
	}

}
